アカウントのデフォルトのイベントテーブルにログを取得する #SnowflakeDB
はじめに
Snowflake では「Snowflake Trail」として Snowflake でのデータパイプラインやアプリケーションのトレース・トラブルシューティング、デバッグ、対応策の実行を簡単かつ効率的に行うために利用できる一連のオブザーバビリティ機能群を提供しています。
このうち Snowpark のコードや UDF、ストアド プロシージャからログ情報をキャプチャできる特別なタイプの Snowflake テーブルであるイベントテーブルが昨年リリースされました。
2024年10月に一般的に有効化された以下の変更バンドルでは、アカウントのデフォルトのイベントテーブルも導入されています。
本記事では、イベントテーブルの概要と、アカウントのデフォルトのイベントテーブルに対してログを収集するまでの手順をまとめてみます。
イベントテーブルの概要
イベントテーブルとは、アカウント内で使用できる特殊な種類のデータベース テーブルです。
主な特徴は以下です。
- ストアドプロシージャや UDF などの Snowflake オブジェクトがテレメトリ データを出力すると、イベント テーブルにデータが自動的に収集される
- 事前定義されたカラム構成を持つ
- テレメトリ データを処理するフレームワークである OpenTelemetry のデータ モデルをサポート
- アカウント内で同時に設定できるイベントテーブルは1つのみ
- これにより、アカウント内で実行されたストアドプロシージャ等に関する以下の情報を自動で収集し一元管理できる
- ログ
- トレース
- メトリクス ※2024年12月時点でプレビュー
- これにより、アカウント内で実行されたストアドプロシージャ等に関する以下の情報を自動で収集し一元管理できる
デフォルトのイベントテーブルとユーザー定義のイベントテーブル
デフォルトのイベントテーブル
現在の Snowflake アカウントにはデフォルトでイベント テーブルが含まれています。これは 2024_06 バンドル によって導入されました(2024/10/7-2024/10/9 に一般的に有効化)。
そのため、ユーザー側で新規のイベントテーブルを定義しなくてもすぐに利用を開始できます。
デフォルトのイベントテーブルとして SNOWFLAKE データベース内に用意された専用の TELEMETRY スキーマ内に定義済みのテーブルが使用されます。
TELEMETRY スキーマ内のオブジェクトは以下です。
- テーブル:SNOWFLAKE.TELEMETRY.EVENTS
- テレメトリ データの出力先として使用されるテーブル
- ビュー:SNOWFLAKE.TELEMETRY.EVENTS_VIEW
- EVENTS テーブルを参照するビュー
- アカウント内で同時に有効化できるイベントテーブルは一つのみのため、ユーザー権限によって特定のレコードのみを返したい場合に、行アクセスポリシーを適用できるビュー
- EVENTS_VIEW に行アクセスポリシーを適用するための事前定義済みのストアドプロシージャ
- ユーザー側で定義した行アクセスポリシーと EVENTS_VIEW のカラムを指定することで、行アクセスポリシーを EVENTS_VIEW にバインドするためのプロシージャ
ユーザー定義のイベントテーブル
デフォルトのイベントテーブルの他にも、任意のイベントテーブルをユーザーで定義することも可能です。この場合 CREATE EVENT TABLE を使用することで、任意のデータベース・スキーマにイベントテーブルを作成できます。
イベントテーブルへのログ収集
デフォルトのイベントテーブルも用意されるようになりましたが、イベントテーブルを作成しただけではログが収集されません。以下の設定が必要です。
- アカウントで使用するイベントテーブルの設定
- テレメトリレベルの設定
アカウントで使用するイベントテーブルの設定
Snowflake アカウント内でテレメトリ データの収集先として指定できるイベントテーブルは一つのみのため、アカウントでアクティブなイベント テーブルを指定する必要があります。
任意のイベントテーブルを作成し、アカウントでアクティブなイベント テーブルとして設定するには、ALTER ACCOUNT コマンドを実行し、 EVENT_TABLE パラメータにイベント テーブルの名前を指定します。
特に設定をしていない場合は、アカウント内のデフォルトのイベントテーブル(SNOWFLAKE.TELEMETRY.EVENTS)が設定されています。
アカウントのイベントテーブルを確認するには以下を実行します。
--アカウントのイベントテーブルを確認
SHOW PARAMETERS LIKE 'event_table' IN ACCOUNT;
特に変更していない場合、以下のような出力でした。
>SHOW PARAMETERS LIKE 'event_table' IN ACCOUNT;
+-------------+----------------------------+----------------------------+-------+-----------------------------------------+--------+
| key | value | default | level | description | type |
|-------------+----------------------------+----------------------------+-------+-----------------------------------------+--------|
| EVENT_TABLE | snowflake.telemetry.events | snowflake.telemetry.events | | Event destination for the given target. | STRING |
+-------------+----------------------------+----------------------------+-------+-----------------------------------------+--------+
任意のイベントテーブルをアクティブに設定するには、イベントテーブル作成後に以下を実行します。
--アカウントのアクティブな任意のイベントテーブルを設定
ALTER ACCOUNT SET EVENT_TABLE = my_database.my_schema.my_events;
テレメトリレベルの設定
アカウントのイベントテーブルを設定後、さらにどの範囲のどのレベルまでテレメトリ データをを取得するかの設定も必要です。これにより、テレメトリ データが取得されます。
関連するパラメータは以下です。
- ログ
- トレース
- トレースレベルの設定を行う
- TRACE_LEVEL パラメーターを任意の階層で設定
- ALWAYS、ON_EVENT または OFF
- デフォルトは OFF
- TRACE_LEVEL パラメーターを任意の階層で設定
- トレースレベルの設定を行う
- メトリクス
- 執筆時点でパブリックプレビュー
- サポートされる言語は Python と Java
- METRIC_LEVEL パラメーターを任意の階層で設定
- ALL または NONE
- デフォルトは NONE
各パラメータは、他のパラメータのように、各階層で設定可能です。
- アカウント
- データベース、スキーマ
- オブジェクト(ストアドプロシージャ)など
これにより、アカウント内すべてや任意のデータベース内のオブジェクトのみ、など任意のオブジェクトのテレメトリ データを取得するように構成できます。
また、下位レベルのオブジェクトの LOG_LEVEL を設定することで、階層内の上位レベルで設定された LOG_LEVEL を上書きできます。セッションパラメーター層とオブジェクトパラメーター層の両方で LOG_LEVEL が設定されている場合は、最も詳細な LOG_LEVEL が使用されます。
詳細は以下をご参照ください。
アクセス制御
オブジェクトのログレベルを設定
オブジェクト(データベース、スキーマ など)レベルでログレベルを設定するには、以下の権限が必要です。
- アカウントレベルのログ設定権限
- 対象のオブジェクトに対する Modify 権限
例として、データベースレベルでログレベルを設定する場合は、以下のように権限を付与します。
--ログレベルの設定ロールを作成
--accountレベルのログ設定権限とデータベースレベルの場合はそのModify権限が必要
USE ROLE USERADMIN;
CREATE OR REPLACE ROLE log_admin;
GRANT ROLE log_admin TO ROLE SYSADMIN;
USE ROLE ACCOUNTADMIN;
GRANT MODIFY LOG LEVEL ON ACCOUNT TO ROLE log_admin;
USE ROLE SECURITYADMIN;
GRANT MODIFY ON DATABASE <対象のデータベース> TO ROLE log_admin;
デフォルトのイベントテーブルを閲覧する権限
デフォルトのイベントテーブルを閲覧する際は、以下の専用のアプリケーションロールが用意されています
- EVENTS_VIEWER
- EVENTS_VIEW に対する参照権限
- EVENTS_ADMIN
- デフォルトのイベントテーブルに対する以下の権限
- SELECT, TRUNCATE, DELETE
- EVENTS_VIEW に対する参照権限
- EVENTS_VIEW に行アクセスポリシーを適用する事前定義済みのプロシージャに対する USAGE
- デフォルトのイベントテーブルに対する以下の権限
アカウントロールへの権限継承例
USE ROLE ACCOUNTADMIN;
GRANT APPLICATION ROLE SNOWFLAKE.EVENTS_VIEWER TO ROLE log_admin;
コスト
基本的にはサーバーレス コンピューティング モデルに基づき請求されます。
詳細は以下をご参照ください。
試してみる
ここでは、アカウント内の指定のデータベース内に作成したストアドプロシージャのログをデフォルトのイベントテーブルに取得するまでをやってみます。
事前準備
はじめに、アカウントレベルの各種設定値を確認します。
USE ROLE SYSADMIN;
--アカウントのイベントテーブルを確認:デフォルトは snowflake.telemetry.events
SHOW PARAMETERS LIKE 'event_table' IN ACCOUNT;
--アカウントレベルのログレベルの設定を確認:デフォルトはNONE
SHOW PARAMETERS LIKE 'log_level' IN ACCOUNT;
以下のコマンドで検証用のサンプルのオブジェクトを作成します。
USE ROLE SYSADMIN;
--ログの取得先とするデータベースを作成
CREATE OR REPLACE DATABASE TELEMETRY_TEST_DB;
USE SCHEMA TELEMETRY_TEST_DB.PUBLIC;
--サンプルテーブルを作成
CREATE OR REPLACE TABLE parent (ID INTEGER);
CREATE OR REPLACE TABLE child (ID INTEGER);
--Snowflakeスクリプトでストアドプロシージャを定義
CREATE OR REPLACE PROCEDURE insert_data()
RETURNS VARCHAR NOT NULL
LANGUAGE SQL
AS
$$
BEGIN
BEGIN TRANSACTION;
INSERT INTO telemetry_test_db.public.parent VALUES (1);
SELECT 1/0; --エラーを発生させる
INSERT INTO telemetry_test_db.public.child VALUES (1);
COMMIT;
RETURN 'complete';
EXCEPTION
WHEN OTHER THEN
ROLLBACK;
RAISE;
END;
$$
;
ゼロ除算によるエラーが発生する設定なので、ストアドプロシージャを実行すると、以下のエラーとなります。
--プロシージャを実行
>call insert_data();
100051 (22012): Uncaught exception of type 'STATEMENT_ERROR' on line 5 at position 4 : Division by zero
この状態でイベントテーブルを参照しても、上記の実行に関するログは確認できません。
USE ROLE ACCOUNTADMIN;
SELECT * FROM SNOWFLAKE.TELEMETRY.EVENTS ORDER BY TIMESTAMP DESC;
ログレベルの設定
ここではデータベースレベルでログレベルの設定が可能なカスタムロール(log_admin
)を作成します。
--ログレベルの設定ロールを作成
--accountレベルのログ設定とデータベースレベルの場合はそのModifyが必要
USE ROLE USERADMIN;
CREATE OR REPLACE ROLE log_admin;
GRANT ROLE log_admin TO ROLE SYSADMIN;
USE ROLE ACCOUNTADMIN;
GRANT MODIFY LOG LEVEL ON ACCOUNT TO ROLE log_admin;
USE ROLE SECURITYADMIN;
GRANT MODIFY ON DATABASE TELEMETRY_TEST_DB TO ROLE log_admin;
--showコマンドを実行するためにデータベースへのusageを付与
GRANT USAGE ON DATABASE TELEMETRY_TEST_DB TO ROLE log_admin;
データベースのログレベルに関するパラメータを設定します。
--データベースレベルで LOG LEVLE を設定する
USE ROLE log_admin;
--確認
SHOW PARAMETERS LIKE '%LOG_LEVEL%' IN DATABASE TELEMETRY_TEST_DB;
--ログレベルを「WARN」に設定
ALTER DATABASE TELEMETRY_TEST_DB SET LOG_LEVEL = WARN;
SHOW PARAMETERS LIKE '%LOG_LEVEL%' IN DATABASE TELEMETRY_TEST_DB;
出力
>SHOW PARAMETERS LIKE '%LOG_LEVEL%' IN DATABASE TELEMETRY_TEST_DB;
+-----------+-------+---------+----------+----------------------------------------+--------+
| key | value | default | level | description | type |
|-----------+-------+---------+----------+----------------------------------------+--------|
| LOG_LEVEL | WARN | OFF | DATABASE | LOG_LEVEL to use when filtering events | STRING |
+-----------+-------+---------+----------+----------------------------------------+--------+
1 Row(s) produced. Time Elapsed: 0.130s
イベントテーブルにログを取得する
アカウントのイベントテーブルの設定と、データベースのログレベルを設定したので、この状態で再度プロシージャを実行します。
--再度プロシージャを実行
USE ROLE SYSADMIN;
USE SCHEMA TELEMETRY_TEST_DB.PUBLIC;
call insert_data();
--1分程経過したらイベントテーブルをクエリ
USE ROLE ACCOUNTADMIN;
SELECT * FROM SNOWFLAKE.TELEMETRY.EVENTS ORDER BY TIMESTAMP DESC;
以下のようにログの出力を確認できます。※何度か実行しています
観測されたタイムスタンプやリソース、レコード情報などが記録されています。
{
"db.user": "<ユーザー>",
"snow.database.id": 61,
"snow.database.name": "TELEMETRY_TEST_DB",
"snow.executable.id": 613,
"snow.executable.name": "INSERT_DATA():VARCHAR(16777216)",
"snow.executable.type": "PROCEDURE",
"snow.owner.id": 4,
"snow.owner.name": "SYSADMIN",
"snow.query.id": "01b8e892-0001-fb39-0001-f082000871ea",
"snow.schema.id": 92,
"snow.schema.name": "PUBLIC",
"snow.session.id": 545916113682718,
"snow.session.role.primary.id": 4,
"snow.session.role.primary.name": "SYSADMIN",
"snow.user.id": 1,
"snow.warehouse.id": 4,
"snow.warehouse.name": "COMPUTE_WH",
"telemetry.sdk.language": "sql"
}
{
"exception.escaped": true,
"exception.message": "Uncaught exception of type 'STATEMENT_ERROR' on line 5 at position 4 : Division by zero",
"exception.type": "100051"
}
デフォルトのイベントテーブルを閲覧する権限をカスタムロールに付与
この場合、予め用意されているアプリケーションロールを任意のロールに付与すればよいです。
--イベントテーブル閲覧用の権限を付与
USE ROLE ACCOUNTADMIN;
GRANT APPLICATION ROLE SNOWFLAKE.EVENTS_VIEWER TO ROLE log_admin;
--イベントテーブルビューをクエリできるようになる
USE ROLE log_admin;
SELECT * FROM SNOWFLAKE.TELEMETRY.EVENTS_VIEW ORDER BY TIMESTAMP DESC;
さいごに
アカウントでデフォルトで利用できるイベントテーブルにログを取得するまでの手順をまとめてみました。
こちらの内容が何かの参考になれば幸いです。